home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
pov
/
source
/
point.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-29
|
8KB
|
276 lines
/****************************************************************************
* point.c
*
* This module implements the point & spot light source primitive.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
METHODS Light_Source_Methods =
{
All_Light_Source_Intersections,
Inside_Light_Source, Light_Source_Normal,
Copy_Light_Source,
Translate_Light_Source, Rotate_Light_Source,
Scale_Light_Source, Transform_Light_Source, Invert_Light_Source,
Destroy_Light_Source
};
static DBL cubic_spline PARAMS(( DBL low,DBL high,DBL pos));
int All_Light_Source_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
if (((LIGHT_SOURCE *)Object)->Children != NULL)
if (Ray_In_Bounds (Ray, ((LIGHT_SOURCE *)Object)->Children->Bound))
if (All_Intersections (((LIGHT_SOURCE *)Object)->Children, Ray, Depth_Stack))
return (TRUE);
return (FALSE);
}
int Inside_Light_Source (IPoint, Object)
VECTOR *IPoint;
OBJECT *Object;
{
if (((LIGHT_SOURCE *)Object)->Children != NULL)
if (Inside_Object (IPoint, ((LIGHT_SOURCE *)Object)->Children))
return (TRUE);
return (FALSE);
}
void Light_Source_Normal (Result, Object, IPoint)
OBJECT *Object;
VECTOR *Result, *IPoint;
{
if (((LIGHT_SOURCE *)Object)->Children != NULL)
Normal (Result, ((LIGHT_SOURCE *)Object)->Children,IPoint);
}
void Translate_Light_Source (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
VAddEq (((LIGHT_SOURCE *) Object)->Center, *Vector);
VAddEq (((LIGHT_SOURCE *) Object)->Points_At, *Vector);
Translate_Object (((LIGHT_SOURCE *)Object)->Children, Vector);
}
void Rotate_Light_Source (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Rotation_Transform (&Trans, Vector);
Transform_Light_Source(Object, &Trans);
}
void Scale_Light_Source (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Scaling_Transform (&Trans, Vector);
Transform_Light_Source(Object, &Trans);
}
void Invert_Light_Source (Object)
OBJECT *Object;
{
Invert_Object (((LIGHT_SOURCE *)Object)->Children);
}
void Transform_Light_Source (Object, Trans)
OBJECT *Object;
TRANSFORM *Trans;
{
MTransPoint (&((LIGHT_SOURCE *) Object)->Center,
&((LIGHT_SOURCE *) Object)->Center, Trans);
MTransPoint (&((LIGHT_SOURCE *) Object)->Points_At,
&((LIGHT_SOURCE *) Object)->Points_At, Trans);
MTransPoint (&((LIGHT_SOURCE *) Object)->Axis1,
&((LIGHT_SOURCE *) Object)->Axis1, Trans);
MTransPoint (&((LIGHT_SOURCE *) Object)->Axis2,
&((LIGHT_SOURCE *) Object)->Axis2, Trans);
Transform_Object (((LIGHT_SOURCE *)Object)->Children, Trans);
}
void Destroy_Light_Source (Object)
OBJECT *Object;
{
int i;
if (((LIGHT_SOURCE *)Object)->Light_Grid != NULL)
{
for (i = 0; i < ((LIGHT_SOURCE *)Object)->Area_Size1; i++)
free(((LIGHT_SOURCE *)Object)->Light_Grid[i]);
free(((LIGHT_SOURCE *)Object)->Light_Grid);
}
Destroy_Object (((LIGHT_SOURCE *)Object)->Children);
free (Object);
}
COLOUR **Create_Light_Grid (Size1, Size2)
int Size1, Size2;
{
COLOUR **New;
int i;
New = (COLOUR **)malloc (Size1 * sizeof (COLOUR *));
if (New == NULL)
MAError ("area light");
for (i = 0; i < Size1; i++)
{
New[i] = (COLOUR *)malloc (Size2 * sizeof (COLOUR));
if (New[i] == NULL)
MAError ("area light");
}
return (New);
}
LIGHT_SOURCE *Create_Light_Source ()
{
LIGHT_SOURCE *New;
if ((New = (LIGHT_SOURCE *) malloc (sizeof (LIGHT_SOURCE))) == NULL)
MAError ("light_source");
INIT_OBJECT_FIELDS(New, LIGHT_OBJECT, &Light_Source_Methods)
New->Children = NULL;
New->No_Shadow_Flag = TRUE;
Make_Colour(&New->Colour,1.0,1.0,1.0);
Make_Vector(&New->Center,0.0,0.0,0.0);
Make_Vector(&New->Points_At,0.0,0.0,1.0);
Make_Vector(&New->Axis1,0.0,0.0,1.0);
Make_Vector(&New->Axis2,0.0,1.0,0.0);
New->Coeff = 10.0;
New->Radius = 0.35;
New->Falloff = 0.35;
New->Next_Light_Source = NULL;
New->Shadow_Cached_Object = NULL;
New->Light_Grid = NULL;
New->Light_Type = POINT_SOURCE;
New->Area_Light = FALSE;
New->Jitter = FALSE;
New->Track = FALSE;
New->Area_Size1 = 0;
New->Area_Size2 = 0;
New->Adaptive_Level = 100;
return (New);
}
void *Copy_Light_Source (Old)
OBJECT *Old;
{
LIGHT_SOURCE *New;
int i, j;
New = Create_Light_Source ();
*New = *(LIGHT_SOURCE *)Old;
New->Next_Light_Source = NULL;
New->Children = Copy_Object (((LIGHT_SOURCE *)Old)->Children);
if (((LIGHT_SOURCE *)Old)->Light_Grid != NULL)
{
New->Light_Grid = Create_Light_Grid (((LIGHT_SOURCE *)Old)->Area_Size1,
((LIGHT_SOURCE *)Old)->Area_Size2);
for (i = 0; i < ((LIGHT_SOURCE *)Old)->Area_Size1; i++)
for (j = 0; j < ((LIGHT_SOURCE *)Old)->Area_Size2; j++)
New->Light_Grid[i][j] = ((LIGHT_SOURCE *)Old)->Light_Grid[i][j];
}
return (New);
}
/* Cubic spline that has tangents of slope 0 at x == low and at x == high.
For a given value "pos" between low and high the spline value is returned */
static DBL cubic_spline(low, high, pos)
DBL low, high, pos;
{
/* Check to see if the position is within the proper boundaries */
if (pos < low)
return 0.0;
else if (pos > high)
return 1.0;
if (high == low)
return 0.0;
/* Normalize to the interval 0->1 */
pos = (pos - low) / (high - low);
/* See where it is on the cubic curve */
return (3 - 2 * pos) * pos * pos;
}
DBL Attenuate_Light (Light_Source, Light_Source_Ray)
LIGHT_SOURCE *Light_Source;
RAY *Light_Source_Ray;
{
DBL Len,costheta;
DBL Attenuation = 1.0;
VECTOR Spot_Direction;
/* If this is a spotlight then attenuate based on the incidence angle */
if (Light_Source->Light_Type == SPOT_SOURCE)
{
VSub(Spot_Direction, Light_Source->Points_At, Light_Source->Center);
VLength(Len, Spot_Direction);
if (Len > 0.0)
{
VInverseScale(Spot_Direction, Spot_Direction, Len);
VDot(costheta, Light_Source_Ray->Direction, Spot_Direction);
costheta *= -1.0;
if (costheta > 0.0)
{
Attenuation = pow(costheta, Light_Source->Coeff);
/* If there is a soft falloff region associated with the light then
do an interpolation of values between the hot center and the
direction at which light falls to nothing. */
if (Light_Source->Radius > 0.0)
Attenuation *= cubic_spline(Light_Source->Falloff,
Light_Source->Radius,
costheta);
/* printf("Atten: %lg\n", Attenuation); */
}
else
Attenuation = 0.0;
}
else
Attenuation = 0.0;
}
return(Attenuation);
}